package com.ijustyce.fastandroiddev;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Environment;
import android.text.ClipboardManager;
import android.util.DisplayMetrics;
import android.util.Log;

import com.baidu.location.BDLocation;
import com.baidu.location.BDLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.location.Poi;
import com.ijustyce.fastandroiddev.unit.LogCat;
import com.ijustyce.fastandroiddev.unit.ToastUnit;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SuppressWarnings("deprecation")
public class IApplication extends Application {

    public static boolean pw; // 是否已经解锁！
    private static String user = ""; // 正在聊天的用户名
    private static int TAB = 0; // 目前所在的tab
    public static boolean downContacts = true;
    public Map<String, String> infos = new HashMap<>();
    private static List<Activity> allActivity = new ArrayList<>();
    public static String read, total;

    private LocationClient mLocationClient;
    private MyLocationListener mMyLocationListener;
    private LocationClientOption option;
    private static String location;
    private static double latitude, longitude;

    private Context context;

    @Override
    public void onCreate() {
        super.onCreate();

        context = this;
        LogCat.e("===IApplication===", "i created now ...");
        initFiles();

        ToastUnit.setPkg(context.getPackageName(), context);

//        initLocation();
//        startGetLocation();

//        LogCat.setShowLog(false);
//        collectDeviceInfo(context);
//        CrashHandler crashHandler = CrashHandler.getInstance();
//        crashHandler.init(context);

        DisplayMetrics dm = getResources().getDisplayMetrics();

        ImageLoaderConfiguration config = new ImageLoaderConfiguration
                .Builder(context)
                .memoryCacheExtraOptions(dm.widthPixels, dm.heightPixels)
                .build();
        ImageLoader.getInstance().init(config);
    }

    public static String getLocation() {

        return location;
    }

    public static double getLatitude(){
        return  latitude;
    }

    public static double getLongitude(){
        return longitude;
    }

    public void startGetLocation() {

        if(!isConnected()){
            return;
        }
        mLocationClient.registerLocationListener(mMyLocationListener);
        mLocationClient.start();
    }

    private void stopGetLocation() {

        if (mLocationClient != null && mLocationClient.isStarted()) {
            mLocationClient.stop();
            mLocationClient.unRegisterLocationListener(mMyLocationListener);
        }
    }

    private void initLocation() {

        if(option == null) {
            option = new LocationClientOption();
            option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);//设置定位模式
            option.setCoorType("gcj02");//返回的定位结果是百度经纬度，默认值gcj02
            int span = 1000 *60; // 1分钟定位一次
            option.setScanSpan(span);
            option.setIsNeedAddress(true);
        }

        if(mLocationClient == null){
            mLocationClient = new LocationClient(this.getApplicationContext());
            mMyLocationListener = new MyLocationListener();
            mLocationClient.setLocOption(option);
        }
    }

    /**
     * 实现实时位置回调监听
     */
    public class MyLocationListener implements BDLocationListener {

        @Override
        public void onReceiveLocation(BDLocation location) {
            //Receive Location
            longitude = location.getLongitude();
            latitude = location.getLatitude();
            StringBuffer sb = new StringBuffer(256);
            sb.append("time : ");
            sb.append(location.getTime());
            sb.append("\nerror code : ");
            sb.append(location.getLocType());
            sb.append("\nlatitude : ");
            sb.append(latitude);
            sb.append("\nlongitude : ");
            sb.append(longitude);
            sb.append("\nradius : ");
            sb.append(location.getRadius());
            if (location.getLocType() == BDLocation.TypeGpsLocation) {// GPS定位结果
                sb.append("\nspeed : ");
                sb.append(location.getSpeed());// 单位：公里每小时
                sb.append("\nsatellite : ");
                sb.append(location.getSatelliteNumber());
                sb.append("\nheight : ");
                sb.append(location.getAltitude());// 单位：米
                sb.append("\ndirection : ");
                sb.append(location.getDirection());
                sb.append("\naddr : ");
                sb.append(location.getAddrStr());
                sb.append("\ndescribe : ");
                sb.append("gps定位成功");

            } else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {// 网络定位结果
                sb.append("\naddr : ");
                sb.append(location.getAddrStr());
                //运营商信息
                sb.append("\noperationers : ");
                sb.append(location.getOperators());
                sb.append("\ndescribe : ");
                sb.append("网络定位成功");
            } else if (location.getLocType() == BDLocation.TypeOffLineLocation) {// 离线定位结果
                sb.append("\ndescribe : ");
                sb.append("离线定位成功，离线定位结果也是有效的");
            } else if (location.getLocType() == BDLocation.TypeServerError) {
                sb.append("\ndescribe : ");
                sb.append("服务端网络定位失败，可以反馈IMEI号和大体定位时间到loc-bugs@baidu.com，会有人追查原因");
            } else if (location.getLocType() == BDLocation.TypeNetWorkException) {
                sb.append("\ndescribe : ");
                sb.append("网络不同导致定位失败，请检查网络是否通畅");
            } else if (location.getLocType() == BDLocation.TypeCriteriaException) {
                sb.append("\ndescribe : ");
                sb.append("无法获取有效定位依据导致定位失败，一般是由于手机的原因，处于飞行模式下一般会造成这种结果，可以试着重启手机");
            }
            sb.append("\nlocationdescribe : ");// 位置语义化信息
            sb.append(location.getLocationDescribe());
            List<Poi> list = location.getPoiList();// POI信息
            if (list != null) {
                sb.append("\npoilist size = : ");
                sb.append(list.size());
                for (Poi p : list) {
                    sb.append("\npoi= : ");
                    sb.append(p.getId() + " " + p.getName() + " " + p.getRank());
                }
            }
            Log.i("BaiduLocationApiDem", sb.toString());
        }
    }

    /**
     * whether is connected to network .
     *
     * @return true if connect or return false
     */
    public boolean isConnected() {

        ConnectivityManager conManager = (ConnectivityManager) getBaseContext()
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = conManager.getActiveNetworkInfo();
        return networkInfo != null && networkInfo.isAvailable();
    }

    public String initFiles() {

        File f = context.getExternalFilesDir(null);
        if (f == null){
            f = Environment.getExternalStorageDirectory();
            if (f == null){
                f = context.getFilesDir();
            }else{
                f = new File(f.getAbsolutePath() + "/fastDroid/");
                f.mkdirs();
            }
        }
        File tmp = new File(f.getAbsolutePath() + "/.tmp/");
        if (!tmp.exists()) {
            tmp.mkdirs();
        }

        File record = new File(f.getAbsolutePath() + "/record/");
        if (!record.exists()) {
            record.mkdirs();
        }
        return f.getAbsolutePath();
    }

    /**
     * 收集设备参数信息
     *
     * @param context context
     */
    public void collectDeviceInfo(Context context) {
        try {
            PackageManager pm = context.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);

            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                infos.put("versionName", versionName);
                infos.put("versionCode", versionCode);
            }
        } catch (PackageManager.NameNotFoundException e) {
            LogCat.e(e.getLocalizedMessage());
        }

        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                infos.put(field.getName(), field.get(null).toString());
            } catch (Exception e) {
                LogCat.e(e.getLocalizedMessage());
            }
        }
    }

    public static void setUser(String user) {

        if (IApplication.user == null) {
            return;
        }
        if (user == null) {
            user = "";
        }
        IApplication.user = user;
    }

    public void pushActivity(Activity activity) {

        allActivity.add(activity);
    }

    public void moveActivity(Activity activity) {

        allActivity.remove(activity);
    }

    public void logOut() {

        Collection<Activity> remove = new ArrayList<>();
        Activity main = null;
        for (Activity tmp : allActivity) {
            if (tmp == null) {
                continue;
            }

            //  找到最近一次放入的MainActivity对象，
            if (main == null && getClassName(tmp).equals("MainActivity")) {
                main = tmp;
                continue;
            }
            tmp.finish();
            remove.add(tmp);
        }
        if (main != null) {
            main.finish();
        }
        allActivity.removeAll(remove);
        System.gc();
        System.exit(0);
    }


    public void finishAllActivity() {

        Collection<Activity> remove = new ArrayList<>();
        Activity main = null;
        for (Activity tmp : allActivity) {
            if (tmp == null) {
                continue;
            }

            //  找到最近一次放入的MainActivity对象，
            if (main == null && getClassName(tmp).equals("MainActivity")) {
                main = tmp;
                continue;
            }
            tmp.finish();
            remove.add(tmp);
        }
        if (main != null) {
            main.finish();
        }
        allActivity.removeAll(remove);
    }

    /**
     * finish all activity except className
     *
     * @param className like MainActivity
     */
    public void finishExcept(String className) {

        if (allActivity == null) {
            return;
        }
        List<Activity> remove = new ArrayList<>();
        for (Activity tmp : allActivity) {
            if (tmp == null) {
                continue;
            }
            String tmpClass = getClassName(tmp);
            if (!tmpClass.equals(className)) {
                remove.add(tmp);
                tmp.finish();
            }
        }
        allActivity.remove(remove);
    }

    private String getClassName(Activity activity){

        if (activity == null){
            return "";
        }
        String className = activity.getLocalClassName();
        String arr[] = className.split("\\.");
        int size = arr.length;

        if (size < 1){
            LogCat.i("===getClassName()===", "getLocalClassName() is "
                    + className + " length is 0 ");
            return className;
        }

        String res = arr[size -1];

        LogCat.i("===getClassName()===", "getLocalClassName() is "
                + className + " className is " + res);

        return res;
    }

    public void finishOther() {

        if (allActivity == null) {
            return;
        }
        List<Activity> remove = new ArrayList<>();
        for (Activity tmp : allActivity) {
            if (tmp == null) {
                continue;
            }
            String className = getClassName(tmp);
            if (!className.equals("MainActivity")) {
                remove.add(tmp);
                tmp.finish();
            }
        }
        allActivity.remove(remove);
    }

    public void finishObject(String className) {

        if (allActivity == null) {
            return;
        }
        Activity remove = null;
        for (Activity tmp : allActivity) {
            if (getClassName(tmp).equals(className)) {
                remove = tmp;
                tmp.finish();
            }
        }
        allActivity.remove(remove);
    }

    public static String getUser() {

        if (user == null) {
            user = "";
        }
        return user;
    }

    public static boolean getPw() {

        return pw;
    }

    public static int getTab() {

        return TAB;
    }

    public static void setPw(boolean value) {

        pw = value;
    }

//    public static boolean isOut(){
//
//        return isOut;
//    }

    public static void setTab(int tab) {

        TAB = tab;
    }

    /**
     * read preferences file and return value if possible or return null
     *
     * @param key      key
     * @param fileName fileName
     * @return value pf key
     */
    public String getPreferences(String key, String fileName) {

        SharedPreferences shared = getSharedPreferences(fileName,
                Context.MODE_PRIVATE);

        return shared.getString(key, "null");
    }

    /**
     * read preferences file and return value if possible or return null
     *
     * @param key      key
     * @param fileName fileName
     * @return value pf key
     */
    public Boolean getPreferences(String key, String fileName, Boolean def) {

        SharedPreferences shared = getSharedPreferences(fileName,
                Context.MODE_PRIVATE);

        return shared.getBoolean(key, def);
    }

    /**
     * set preferences file value
     *
     * @param key      key of preference file
     * @param value    value of key
     * @param fileName preference file name
     */
    public void setPreferences(String key, String value, String fileName) {

        SharedPreferences shared = getSharedPreferences(fileName,
                Context.MODE_PRIVATE);

        shared.edit().putString(key, value).apply();
    }

    /**
     * set preferences file value
     *
     * @param key      key of preference file
     * @param value    value of key
     * @param fileName preference file name
     */
    public void setPreferences(String key, Boolean value, String fileName) {

        SharedPreferences shared = getSharedPreferences(fileName,
                Context.MODE_PRIVATE);

        shared.edit().putBoolean(key, value).apply();
    }

    /**
     * get string of strings.xml
     *
     * @param id string id like R.string.hello
     * @return string value
     */
    public String getStringValue(int id) {

        return getResources().getString(id);
    }

    /**
     * return VersionName
     *
     * @param context Activity.this
     * @return versionName
     */
    public String getVersionName(Context context) {

        try {
            PackageManager manager = context.getPackageManager();
            PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
            return info.versionName;
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * return VersionCode
     *
     * @param context Activity.this
     * @return versionCode
     */
    public static int getVersionCode(Context context) {

        try {
            PackageManager manager = context.getPackageManager();
            PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
            int version = info.versionCode;

            return version;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * return packageName
     *
     * @param context Activity.this
     * @return packageName
     */
    public static String getPkgName(Context context) {

        try {
            PackageManager manager = context.getPackageManager();
            PackageInfo info = manager.getPackageInfo(context.getPackageName(), 0);
            return info.applicationInfo.loadLabel(
                    context.getPackageManager()).toString();
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * @param context Activity.this
     * @return pkgName+" "+versionName , if fail return ""
     */
    public String getVersion(Context context) {

        return getPkgName(context) + getVersionName(context);
    }

    /**
     * 判断Activity是否在运行，Android只能有一个Activity在运行，其他的状态，一定是未运行
     *
     * @return true if running or return false
     */
    public boolean isTop() {

        String packageName = this.getPackageName();
        ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningTaskInfo> appTask = activityManager.getRunningTasks(1);

        if (appTask != null && appTask.size() > 0) {
            if (appTask.get(0).topActivity.toString().contains(packageName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断Activity是否在运行，Android只能有一个Activity在运行，其他的状态，一定是未运行
     *
     * @param className class name of activity , do not contain package name , but must contain '.' , like: .MainActivity
     * @return true if running or return false
     */
    public boolean isTop(String className) {

        String packageName = this.getPackageName() + className;
        ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningTaskInfo> appTask = activityManager.getRunningTasks(1);

        if (appTask != null && appTask.size() > 0) {
            if (appTask.get(0).topActivity.toString().contains(packageName)) {
                return true;
            }
        }
        return false;
    }

    /**
     * set text to clipboard
     *
     * @param text the text set to clipboard
     */
    public void setClipboard(String text) {

        ClipboardManager clipboard = (ClipboardManager) getSystemService
                (Context.CLIPBOARD_SERVICE);

        clipboard.setText(text);
    }
}